/**
 *  @file
 *  @brief   柱坐标系第二种定义方式
 *  @author  xiaochangjiang
 *  @date    2024.04.19
 *  @version  v1.0
 *  @par Copyright(c):  ShenGong  Simulation corporation
 */

#pragma once
#include "DataStructure/Common/SGObject.h"
#include "DataStructure/Input/Coordinate/ICoordinate.h"

SG_DATASTRUCTURE_FEM_NAMESPACE_OPEN
/** @brief 柱坐标系第二种定义方式
 *
 * 通过一个参考坐标系和三个节点定义坐标系基矢量方向, `m_A`定义坐标系原点。
 * 如果m_RID为零或为空，则参考坐标系使用基本坐标系。
 * 矢量`m_B - `m_A` 定义坐标系的Z轴。 `m_C`确定方位角原点平面。
 */
struct DECLSPEC Cylinder2Coord : public ICoordinate
{
    Cylinder2Coord ();
    /** 构造函数
     *
     * 传入坐标系Id和 定义坐标系的参考坐标系和 三个参考点坐标
     */
    Cylinder2Coord (SG::DataStructure::Common::Id id,
                    SG::DataStructure::Common::Id ref,
                    const SG::Algebra::Point&     PA,
                    const SG::Algebra::Point&     PB,
                    const SG::Algebra::Point&     PC);
    virtual ~Cylinder2Coord () = default;

    /** @brief 查询坐标系状态
     * 当坐标系的三个节点的参考坐标系为0，或者全都已经被初始化， 应返回Status_Ready
     */
    virtual SG::DataStructure::FEM::CoordStatus QueryStatus (ICoordinatePArray& coordSet) const override;

    /** @brief 传入节点的参考坐标系*/
    void SetRefCoordId (std::size_t index, SG::DataStructure::Common::Id refId) override;

    /** @brief 获得定义坐标系的参考点Id， 为了接口的一致性，不应该被调用*/
    virtual void GetRefPoint (_OUT SG::DataStructure::Common::Id& GA,
                              _OUT SG::DataStructure::Common::Id& GB,
                              _OUT SG::DataStructure::Common::Id& GC) const override;

    /** @brief 获得定义坐标系的参考坐标系和参考点*/
    virtual void GetRefPoint (_OUT SG::DataStructure::Common::Id& ref,
                              _OUT SG::Algebra::Point& PA,
                              _OUT SG::Algebra::Point& PB,
                              _OUT SG::Algebra::Point& PC) override;

    /**
     * @brief 通过局部坐标系下分量计算节点在 Basic 坐标系下分量
     *
     * 角度分量单位为度，函数内部将其转换成弧度
     */
    virtual SG::Algebra::Point Trans2Basic (const SG::DataStructure::Common::Real& r,
                                            const SG::DataStructure::Common::Real& theta,
                                            const SG::DataStructure::Common::Real& z) const override;

    SG::DataStructure::Common::Id m_ref;  ///< 参考坐标系的编号
    SG::Algebra::Point            m_PA;   ///< 节点1在参考坐标系中坐标
    SG::Algebra::Point            m_PB;   ///< 节点2在参考坐标系中坐标
    SG::Algebra::Point            m_PC;   ///< 节点3在参考坐标系中坐标
};

///< @brief 柱坐标系数据结构体，通过坐标构建。
struct DECLSPEC CORD2CData : public SGObject
{
    SG::DataStructure::Common::Id m_rId = 0;  /// 独立于此定义的坐标系的标识号坐标系统 Integer > 0; Default = 0;全局基本坐标系
    SG::DataStructure::Common::Real m_a1      = 0.0;  /// 代表坐标系原点的点的X坐标
    SG::DataStructure::Common::Real m_a2      = 0.0;  /// 代表坐标系原点的点的Y坐标
    SG::DataStructure::Common::Real m_a3      = 0.0;  /// 代表坐标系原点的点的Z坐标
    SG::DataStructure::Common::Real m_b1      = 0.0;  /// 代表坐标系Z轴的点的X坐标
    SG::DataStructure::Common::Real m_b2      = 0.0;  /// 代表坐标系Z轴的点的Y坐标
    SG::DataStructure::Common::Real m_b3      = 0.0;  /// 代表坐标系Z轴的点的Z坐标
    SG::DataStructure::Common::Real m_c1      = 0.0;  /// 位于方位角起始所在平面的点的X坐标
    SG::DataStructure::Common::Real m_c2      = 0.0;  /// 位于方位角起始所在平面的点的Y坐标
    SG::DataStructure::Common::Real m_c3      = 0.0;  /// 位于方位角起始所在平面的点的Z坐标
    SG::DataStructure::Common::Id   m_dominId = 0;    ///

    static SG::DataStructure::FEM::CoordTypes GetType ()
    {
        return SG::DataStructure::FEM::CoordTypes::COORDTYPE_Cylinder2;
    };

    Cylinder2Coord GetCylinder2Coord ();
};

///< @brief 判断CORD2S数据是否相等
DECLSPEC bool operator== (const CORD2CData& a, const CORD2CData& b);

SG_DATASTRUCTURE_FEM_NAMESPACE_CLOSE